package org.ytu.classifier;

import org.ytu.classifier.algorithm.Partitioner;
import org.ytu.classifier.algorithm.SoundClassifier;
import org.ytu.classifier.beans.AnalyseBean;
import org.ytu.classifier.kmeans.FeaturedData;
import org.ytu.classifier.kmeans.Kmeans;
import org.ytu.classifier.util.MathUtil;

import javax.swing.*;
import javax.swing.filechooser.FileNameExtensionFilter;
import java.io.File;
import java.util.*;

public class Main {
   private static boolean[] algorithmTypeParams;
   private static int[] kParams;
   private static int[] filterParams;
   private static int[] cepstralCoefficientParams;

   public static void main(String[] args) {
      //selectFileToPartition();
      runAlgorithmForFiles();
   }

   //TODO aşağıdaki metodlar statik
   public static List<FeaturedData> getFeaturedDataList(Map<String, List<List<Double>>> resultMap, int cepstralCoefficients) {
      List<FeaturedData> allList = new ArrayList<FeaturedData>();
      FeaturedData data;
      for (Map.Entry<String, List<List<Double>>> speciesFeatures : resultMap.entrySet()) {
         String animalSpecies = speciesFeatures.getKey();
         List<List<Double>> frameFeatures = speciesFeatures.getValue();
         for (List<Double> frameFeature : frameFeatures) {
            data = new FeaturedData(animalSpecies, cepstralCoefficients);
            data.setFeatures(MathUtil.toPrimitiveDouble(frameFeature));
            allList.add(data);
         }
      }
      return allList;
   }

   public static void selectFileToPartition() {
      File fileToRemoveSilence;
      FileNameExtensionFilter filter = new FileNameExtensionFilter("Wav dosyası", "wav");

      JFileChooser jfc = new JFileChooser();
      jfc.addChoosableFileFilter(filter);
      jfc.showOpenDialog(jfc);
      fileToRemoveSilence = jfc.getSelectedFile();
      partition(fileToRemoveSilence);
   }

   public static void partition(File fileToRemoveSilence) {
      Partitioner partitioner = new Partitioner();
      partitioner.startPartition(fileToRemoveSilence);
   }

   public static void runAlgorithmForFiles() {
      JFileChooser jfc = new JFileChooser();
      jfc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
      jfc.showOpenDialog(jfc);
      File directory = jfc.getSelectedFile();
      String[] fileList = listDir(directory);
      List<Double> totalErrorList = new ArrayList<Double>();
      List<Double> clusterSuccessRateList = new ArrayList<Double>();
      List<AnalyseBean> analyses = new ArrayList<AnalyseBean>();

      initParams();//test edilecek parametreler atanıyor
      for (boolean isMel : algorithmTypeParams) {
         for (int k : kParams) {
            for (int cepstralCoefficients : cepstralCoefficientParams) {
               for (int numberOfFilters : filterParams) {

                  Map<String, List<List<Double>>> resultMap = new HashMap<String, List<List<Double>>>();

                  for (String fileName : fileList) {
                     if (fileName.contains("_cleaned") || !fileName.contains("_")) {
                        continue;
                     }

                     SoundClassifier classifier = new SoundClassifier(cepstralCoefficients, numberOfFilters, isMel);
                     List<List<Double>> resultList = classifier.startAlgorithm(directory.getAbsolutePath() + "\\" + fileName);
                     String key = fileName.substring(0, fileName.lastIndexOf("_"));

                     if (!resultMap.containsKey(key)) {
                        resultMap.put(key, resultList);
                     } else {
                        resultMap.get(key).addAll(resultList);
                     }
                  }
                  List<FeaturedData> allList = getFeaturedDataList(resultMap, cepstralCoefficients);

                  Kmeans kmeans = new Kmeans(k, allList, cepstralCoefficients, numberOfFilters, resultMap.size(), isMel);
                  AnalyseBean analyse = kmeans.startAlgorithm();
                  totalErrorList.add(analyse.getTotalError());
                  clusterSuccessRateList.add(analyse.getClusterSuccessRate());
                  analyses.add(analyse);
               }
            }
         }
      }
      sortAnalyses(analyses);
   }

   public static void sortAnalyses(List<AnalyseBean> analyses) {
      Collections.sort(analyses, new Comparator<AnalyseBean>() {

         public int compare(AnalyseBean a1, AnalyseBean a2) {
            if (a1.getClusterSuccessRate() == a2.getClusterSuccessRate()) {
               return a1.getTotalError() == a2.getTotalError() ? 0 :
                       a1.getTotalError() < a2.getTotalError() ? -1 : 1;
            } else {
               return a1.getClusterSuccessRate() > a2.getClusterSuccessRate() ? -1 : 1;
            }
         }
      });
   }

   public static void initParams() {
      algorithmTypeParams = new boolean[]{true, false};
      kParams = new int[]{2, 5, 8, 11, 13};
      filterParams = new int[]{9, 12};
      cepstralCoefficientParams = new int[]{9, 13};
   }

   public static String[] listDir(File directory) {
      return directory.list();
   }
}
